package com.itfenghuang.day14;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class A03_1线程同步 {
    public static void main(String[] args) {
        /**
         * 多线程安全问题
         * 1.案例: 卖票问题
         *      某电影院正在上映日韩大片, 共100张票, 现在有三个窗口售票
         *      设计一个程序将这些票买完
         *      分析:
         *          三个窗口同时卖票,三个线程 线程任务是相同的
         *          线程任务: 卖票的时候 先判断是否还有票
         *                  如果有票卖出去, 如果没有票就结束
         *          1).自定义类SellTicket 实现Runnable接口
         *          2).重写run()方法
         *              卖票
         *          3).创建三个窗口卖票(线程)
         * 2.卖票问题
         *      1).出现问题
         *          重复卖票
         *      2).出现问题原因
         *          线程在执行线程任务的时候丢失cpu的使用权
         *      3).线程安全问题出现的条件
         *          多个线程;共享数据;有多个语句操作共享数据
         * 3.同步技术
         *      给操作共享数据的代码加锁, 保证在同一时刻只有一个线程来执行操作数据
         *   同步代码块;同步方法;Lock锁
         *   1).同步代码块
         *      格式:synchronized(锁对象){操作共享数据的代码}
         *   2).同步方法
         *      格式:修饰符 synchronized 返回值类型 方法名(方法参数){方法体}
         *      锁对象: this 当前类对象
         *   3).Lock锁
         *      jdk5出现的
         *      Lock 接口
         *          lock() 获取锁
         *          unlock() 释放锁
         *      使用ReentrantLock类的对象来调用加锁解锁的方法
         * 3.使用同步技术的好处和坏处:
         *      好处:解决了多线程安全问题
         *      弊端:影响执行效率
         * 4.死锁问题
         *      两个或多个线程互相持有对方所需要的锁, 又不释放自己手中的锁
         *
         */

//        SellTiket st = new SellTiket();
//        Thread t1 = new Thread(st);
//        t1.setName("窗1");
//        Thread t2 = new Thread(st);
//        t2.setName("窗2");
//        Thread t3 = new Thread(st);
//        t3.setName("窗3");
//        t1.start();
//        t2.start();
//        t3.start();
        Object o1 = new Object();
        Object o2 = new Object();
        new Thread(){
            @Override
            public void run() {
                while(true){
                    synchronized(o1){
                        synchronized (o2){

                            System.out.println("tom有一根左筷子");
                        }
                    }
                }
            }
        }.start();
        new Thread(){
            @Override
            public void run() {
                while(true){
                    synchronized(o2){
                        synchronized (o1){

                            System.out.println("rose有一根右筷子");
                        }
                    }
                }
            }
        }.start();

    }
}

class SellTiket implements Runnable{

    private int total=1000;
    private Object o=new Object();
    //创建锁对象
    private Lock lock = new ReentrantLock();

    //同步代码块
//    @Override
//    public void run() {
//
//        while(true){
//            //同步技术解决线程安全问题: 锁对象唯一
//            synchronized (o){
//                if (total==0){
//                    break;
//                }else if (total>0){
//                    System.out.println(
//                            Thread.currentThread().getName()+"卖了"+total+"张票");
//                    total--;
//                }
//            }
//        }
//    }
    //同步方法
    @Override
    public void run() {

        while(true){
            //同步技术解决线程安全问题: 锁对象唯一
            sellTicket();
            if (total<=0){
                break;
            }


        }
    }
    public synchronized void sellTicket(){

        if (total>0){
            System.out.println(
                    Thread.currentThread().getName()+"卖了"+total+"张票");
            total--;
        }
    }
//    @Override
//    public void run() {
//
//        while(true){
//            //同步技术解决线程安全问题: 锁对象唯一
//            lock.lock();
//                if (total>0){
//                    System.out.println(
//                            Thread.currentThread().getName()+"卖了"+total+"张票");
//                    total--;
//                }
//            //释放锁
//            lock.unlock();
//                if (total==0){
//                    break;
//                }
//
//        }
//    }

}